package cn.tsingmo.otproxy.security;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 加密服务类
 * 提供AES-256-CBC算法的加密和解密功能
 */
public class EncryptionService {
    private static final Logger logger = LoggerFactory.getLogger(EncryptionService.class);
    // 加密算法：AES-256-CBC
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    // 密钥长度：256位
    private static final int KEY_SIZE = 256;
    // 初始化向量长度：16字节
    private static final int IV_LENGTH = 16;

    // 密钥规范
    private final SecretKeySpec secretKeySpec;

    /**
     * 默认构造函数，使用KeyManager提供的默认密钥
     */
    public EncryptionService() {
        this(KeyManager.getEncryptionKey());
    }

    /**
     * 构造函数
     * @param secretKey 加密密钥（Base64编码）
     */
    public EncryptionService(String secretKey) {
        try {
            // 解码Base64密钥
            byte[] keyBytes = Base64.getDecoder().decode(secretKey);
            // 创建密钥规范
            this.secretKeySpec = new SecretKeySpec(keyBytes, "AES");
        } catch (Exception e) {
            logger.error("初始化加密服务失败", e);
            throw new RuntimeException("加密服务初始化失败", e);
        }
    }

    /**
     * 加密数据
     * @param data 待加密的明文数据
     * @return 加密后的密文（包含IV向量，格式：IV + 密文，Base64编码）
     */
    public byte[] encrypt(byte[] data) {
        try {
            // 生成随机IV向量
            byte[] iv = new byte[IV_LENGTH];
            SecureRandom random = new SecureRandom();
            random.nextBytes(iv);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            // 初始化加密器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);

            // 执行加密
            byte[] encryptedData = cipher.doFinal(data);

            // 拼接IV和密文（IV在前，密文在后）
            byte[] result = new byte[iv.length + encryptedData.length];
            System.arraycopy(iv, 0, result, 0, iv.length);
            System.arraycopy(encryptedData, 0, result, iv.length, encryptedData.length);

            return result;
        } catch (Exception e) {
            logger.error("数据加密失败", e);
            throw new RuntimeException("加密失败", e);
        }
    }

    /**
     * 解密数据
     * @param encryptedData 加密数据（包含IV向量，格式：IV + 密文）
     * @return 解密后的明文数据
     */
    public byte[] decrypt(byte[] encryptedData) {
        try {
            // 分离IV向量和密文
            byte[] iv = new byte[IV_LENGTH];
            System.arraycopy(encryptedData, 0, iv, 0, iv.length);
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            byte[] cipherText = new byte[encryptedData.length - IV_LENGTH];
            System.arraycopy(encryptedData, IV_LENGTH, cipherText, 0, cipherText.length);

            // 初始化解密器
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivSpec);

            // 执行解密
            return cipher.doFinal(cipherText);
        } catch (Exception e) {
            logger.error("数据解密失败", e);
            throw new RuntimeException("解密失败", e);
        }
    }
}